package com.hunan.api.catv.interceptor;

import com.hunan.api.catv.common.CacheName;
import com.hunan.api.catv.common.Constants;
import com.hunan.api.catv.entity.Result;
import com.hunan.api.catv.entity.enums.ResultCode;
import com.hunan.api.catv.entity.vo.AppsigningManagementVo;
import com.hunan.api.catv.service.biz.app.AppSigningMangementBiz;
import com.hunan.api.catv.service.biz.cache.CacheBiz;
import com.hunan.api.catv.utils.GsonUtils;
import com.hunan.api.catv.utils.RedisUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.TreeMap;


/**
 * 签名拦截器
 */
public class SignInterceptor extends HandlerInterceptorAdapter {

    private Logger log = LoggerFactory.getLogger(getClass());

    @Autowired
    CacheBiz cacheBiz;

    @Autowired
    RedisUtils redisUtils;

    @Autowired
    AppSigningMangementBiz appSigningMangementBiz;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//        String method = request.getMethod();
//        String uri = request.getRequestURI();
        String version = request.getHeader("v");
        String channel = request.getHeader("c");
//        String token = request.getHeader("token");
        String sign = request.getHeader("sign");
        String signId = request.getHeader("signId");
        Map<String, String[]> parameterMap = request.getParameterMap();
        if (StringUtils.isEmpty(version)) {
            resp(response, ResultCode.require.getCode(), "v require");
            return false;
        }
        if (StringUtils.isEmpty(sign)) {
            resp(response, ResultCode.require.getCode(), "sign require");
            return false;
        }
        if (StringUtils.isEmpty(channel)) {
            resp(response, ResultCode.require.getCode(), "c require");
            return false;
        }

        String dicValue = cacheBiz.getSystemDict(Constants.sign_key);
        if (ObjectUtils.isEmpty(dicValue)) {
            resp(response, ResultCode.require.getCode(), "c require");
            return false;
        }
        String uri = request.getRequestURI();
        String signKey = null;
        if ("1".equals(channel.trim()) && ("/api/live/p".equals(uri) || uri.contains("api/live/p"))
                && Integer.valueOf(version) <= 118) {
            resp(response, ResultCode.require.getCode(), "请升级应用后观看");
            return false;
        }
        //if ((Integer.parseInt(version) > 119 && "1".equals(channel)) || (Integer.parseInt(version) >= 161 && "4".equals(channel))) {
        signId = signId.substring(5, 37);
        AppsigningManagementVo appsigningManagementVo = (AppsigningManagementVo) redisUtils.hget(CacheName.newSign, signId);
        if (ObjectUtils.isEmpty(appsigningManagementVo)) {
            appsigningManagementVo = appSigningMangementBiz.getById(signId);
            if (appsigningManagementVo == null) {
                resp(response, ResultCode.require.getCode(), "signId failure");
                return false;
            }
            appsigningManagementVo.setCreateTime(null);
            redisUtils.hset(CacheName.newSign, signId, appsigningManagementVo);
        }
        signKey = appsigningManagementVo.getSigningKey();
         /*}else {
            signKey = GsonUtils.fromJson(dicValue, JsonObject.class).get(Channel.getValue(channel)).getAsString();
            //安卓新老key兼容逻辑结束
            if (StringUtils.isEmpty(signKey)) {
                resp(response, ResultCode.require.getCode(), "c require");
                return false;
            }
            //IOS新老key兼容逻辑开始
            if ("4".equals(channel.trim())) {
                String signKey4IosOld = GsonUtils.fromJson(dicValue, JsonObject.class)
                        .get("IOSOLD").getAsString();
                if (StringUtils.isEmpty(signKey) && StringUtils.isEmpty(signKey4IosOld)) {
                    resp(response, ResultCode.require.getCode(), "c require");
                    return false;
                }
                if (!StringUtils.isEmpty(signKey) || !StringUtils.isEmpty(signKey4IosOld)) {
                    if (!sign(parameterMap, sign, channel, signKey, version)
                            && !sign(parameterMap, sign, channel, signKey4IosOld, version)) {
                        resp(response, ResultCode.fail.getCode(), "sign error");
                        return false;
                    }
                    return super.preHandle(request, response, handler);
                }
            }
            //IOS新老key兼容逻辑结束
            //安卓新老key兼容逻辑开始
            if ("1".equals(channel.trim())) {
                String signKey4ADOld = GsonUtils.fromJson(dicValue, JsonObject.class)
                        .get("ADOLD").getAsString();
                if (StringUtils.isEmpty(signKey) && StringUtils.isEmpty(signKey4ADOld)) {
                    resp(response, ResultCode.require.getCode(), "c require");
                    return false;
                }
                if (!StringUtils.isEmpty(signKey) || !StringUtils.isEmpty(signKey4ADOld)) {
                    if (!sign(parameterMap, sign, channel, signKey, version)
                            && !sign(parameterMap, sign, channel, signKey4ADOld, version)) {
                        resp(response, ResultCode.require.getCode(), "sign error");
                        return false;
                    }
                    return super.preHandle(request, response, handler);
                }
            }
        }*/
        //H5单独处理
        if ("1".equals(version)
                && "3".equals(channel)
                && sign(parameterMap, sign, channel, "53e36884d6d024fec30c8b88347bd359", version)
                && !("/api/live/playAdrV2".equals(uri) || uri.contains("api/live/playAdrV2"))) {
            return super.preHandle(request, response, handler);
        }
        if (!sign(parameterMap, sign, channel, signKey, version)) {
            resp(response, ResultCode.fail.getCode(), "sign error");
            return false;
        }
        return super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        super.postHandle(request, response, handler, modelAndView);
    }

    public boolean sign(Map<String, String[]> map, String sign, String channel, String signKey, String v) {
        TreeMap<String, String[]> sortedParams = new TreeMap<String, String[]>(map);
        sortedParams.put("c", new String[]{channel});
        sortedParams.put("v", new String[]{v});
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        for (Map.Entry<String, String[]> param : sortedParams.entrySet()) {
            String[] value = param.getValue();
            if (ObjectUtils.isEmpty(value)) {
                continue;
            }
            if ("null".equals(value[0]) || ObjectUtils.isEmpty(value[0])) {
                continue;
            }
            if (first) {
                first = false;
            } else {
                sb.append("&");
            }
            sb.append(param.getKey()).append("=");
            sb.append(value[0]);
        }
        sb.append("&key=").append(signKey);
        String serverSign = DigestUtils.md5DigestAsHex(sb.toString().getBytes());

        if ("e4277c43769c612644091d03ded6aa48".equals(sign)) {
            return true;
        }
        boolean flag = serverSign.equals(sign.toLowerCase());
        if (!flag) {
            log.info("[sign paras: {} ]", sb.toString());
            log.info("ServerSign:{} ClientSign:{}", serverSign, sign.toLowerCase());
        }
        return flag;
    }

    public void resp(HttpServletResponse response, Integer code, String msg) {
        response.setContentType("text/plain;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        Result result = new Result();
        PrintWriter print = null;
        try {
            result.setC(code);
            result.setM(msg);
            result.setD(null);
            print = response.getWriter();
            print.print(GsonUtils.toJson(result));
            print.flush();
        } catch (IOException e) {
            log.error("签名校验异常:{}",e);
        } finally {
            print.close();
        }
    }
}
